/*
 * Algoritmo.c
 *
 *  Created on: 09/10/2011
 *      Author: utn_so
 */

#include "Algoritmo.h"



void EncolarPedido(Solicitud unaSolicitud)
{
	if(strcmp(ArrayConfAlgoritmo[3],"ON")==0)
	{
		char* helpp = malloc(30);
		sprintf(helpp,"Tipo:%c , Sector:%d \n",unaSolicitud.Tipo,unaSolicitud.Sector);
		escribir_logfile("DiscoSO", 0, INFOs, helpp);
		free(helpp);
	}
	if(strcmp(ArrayConfAlgoritmo[1],"SSTF")==0)//SSTF
	{
		while(Encolar(unaSolicitud)==-1)
		{
				/*sleep(0.5);
				printf("No se pudo encolar, cola de pedidos llena. \n");*/
		}
	}
	else ///C-SCAN
	{
		while(Encolar(unaSolicitud)==-1)
		{
			//sleep(1);
			//printf("No se pudo encolar, cola de pedidos llena. \n");
		}
	}
}

int32_t Encolar(Solicitud unaSolicitud)
{
	int32_t i;
	for(i=0;i<TAMANO_COLA;i++)
	{
		if(ColaPedidos[i].Tipo=='0')
		{
			ColaPedidos[i]=unaSolicitud;
			Encolados++;
			//printf("Encolados %d \n ", Encolados);
			//printf("Encolados %d \n ", unaSolicitud.Sector);
			return 0;
		}
	}
	return -1;
}

Paquete* ArmarPaquete(int i)
{
	int z = 0;
	Paquete* unPaquete=malloc(512+1+2+16+4);
	unPaquete->Length=512;
	unPaquete->Tipo=ColaPedidos[i].Tipo;
	unPaquete->Sector=ColaPedidos[i].Sector;
	for(z=0;z<16;z++)
		unPaquete->ID[z]=ColaPedidos[i].ID[z];
	unPaquete->Datos=malloc(512);
	LeerSectorLlenar(ColaPedidos[i].Sector,unPaquete->Datos);
	return unPaquete;
}

void IniciarSSTF()
{
	//printf("Algoritmo con inanición, SSTF \n ");
	Cabezal=0;
	int32_t Atendidos = 0;
	int32_t i = 0;
	IniciarColas();
	int32_t slee15 = atoi(ArrayConfAlgoritmo[15]);
	int32_t slee14 = atoi(ArrayConfAlgoritmo[14]);
	int32_t fd = fileno_unlocked(archDisco);
	posix_fadvise(fd,0,0,1);
	/*for(i=0;i<10;i++)
	{
		Solicitud unPaquete;
		unPaquete.Datos;
		RandomGG(unPaquete.ID,16);
		unPaquete.Tipo='L';
		unPaquete.Sector=rand() % 99;
		EncolarPedido(unPaquete);
	}*/
	while(1)
	{
		///consumir cola de pedidos ColaPedidos y desencolar segun la distancia de pistas
		int64_t distanciaMenor = 100000000;
		int32_t SectorALeer=-1;
		int32_t posicion=-1;
		int32_t cabezalAux=0;
		for(i=0;i<TAMANO_COLA;i++)
		{
			if((ColaPedidos[i].Tipo=='L') | (ColaPedidos[i].Tipo=='E'))
			{
				pthread_mutex_lock (&mutexCabezal);
				cabezalAux=Cabezal;
				int32_t PistaActual = Cabezal / atoi(ArrayConfAlgoritmo[5]);
				int32_t pistaDestino = ColaPedidos[i].Sector / atoi(ArrayConfAlgoritmo[5]);
				ColaPedidos[i].Distancia=abs(PistaActual-pistaDestino)*atoi(ArrayConfAlgoritmo[12]);
				//int32_t posSectorCabezal = Cabezal - PistaActual*(atoi(ArrayConfAlgoritmo[5]));
				//int32_t posSectorDestino=(ColaPedidos[i].Sector-(abs(PistaActual-pistaDestino)*atoi(ArrayConfAlgoritmo[12])));
				//int32_t distanciaAux=posSectorDestino-posSectorCabezal;
				//if((distanciaAux)<0)
				//	distanciaAux= atoi(ArrayConfAlgoritmo[12])-abs(distanciaAux);
				//ColaPedidos[i].Distancia += distanciaAux;
				pthread_mutex_unlock (&mutexCabezal);
				if(ColaPedidos[i].Distancia<distanciaMenor)
				{
					distanciaMenor=ColaPedidos[i].Distancia;
					SectorALeer=ColaPedidos[i].Sector;
					posicion=i;
				}
			}
		}
		if(SectorALeer!=-1)
		{
			Paquete* unPaquete = ArmarPaquete(posicion);
			if(unPaquete->Tipo=='L')
			{
				char* serial;
				serial = Serializar(unPaquete);
				int32_t posta = 0;
				for(int32_t cc = 0; cc<16;cc++)
				{
					if(unPaquete->ID[cc]!=IDTrace[cc])
						posta=1;
				}
				int sendeame;
				if(posta==1)
				{
					if(slee15!=0)
						sleep(atoi(ArrayConfAlgoritmo[15]));
					pthread_mutex_lock (&mutexBuffer);
					sendeame = send(ColaPedidos[posicion].Socket,serial,512+16+1+2+4,0);
					pthread_mutex_unlock (&mutexBuffer);
					if(sendeame<0)
						printf("Error en Send. \n");
				}
				else
					{
					char* Actual = malloc(9);
					Actual=ConvertirCHS(cabezalAux);
	  				char* letsSend = malloc(9*2500);
	  				char* help = malloc(100);
	  				sprintf(help,"Posicion Actual:%s \n",Actual);
	  				strcat(letsSend,help);
	  				Actual="\0";
	  				Actual=ConvertirCHS(unPaquete->Sector);
	  				sprintf(help,"Solicitado:%s \n",Actual);
	  				strcat(letsSend,help);
	  				int32_t saltoPista = 0;
	  				int32_t pasoSector=0;
	  				char* finalSend=(char*)malloc(9*2500);
	  				int32_t unaPistitaOrigen=cabezalAux / atoi(ArrayConfAlgoritmo[5]);;
	  				int32_t unSectorcitoOrigen=cabezalAux - unaPistitaOrigen*(atoi(ArrayConfAlgoritmo[5]));
	  				int32_t unaPistitaDest=unPaquete->Sector / atoi(ArrayConfAlgoritmo[5]);;
	  				int32_t unSectorcitoDest=unPaquete->Sector - unaPistitaDest*(atoi(ArrayConfAlgoritmo[5]));
	  				strcat(letsSend,"Sectores Recorridos: ");
	  				if(unaPistitaOrigen<unaPistitaDest)
	  				{
	  					//Voy subiendo de pistas
	  					while(unaPistitaOrigen!=unaPistitaDest)
	  					{
	  						(sprintf(help,"%d,%d ",unaPistitaOrigen,unSectorcitoOrigen));
	  						strcat(letsSend,help);
	  						unaPistitaOrigen++;
	  						saltoPista++;
	  					}
	  				}
	  				else if (unaPistitaOrigen>unaPistitaDest)
	  				{
	  					//Bajo de pistas
	  					while(unaPistitaOrigen!=unaPistitaDest)
	  					{
	  						(sprintf(help,"%d,%d ",unaPistitaOrigen,unSectorcitoOrigen));
	  						strcat(letsSend,help);
	  						unaPistitaOrigen--;
	  						saltoPista++;
	  					}
	  				}
	  				//Ya estoy en la pista, falta correr sobre la misma
  					while(unSectorcitoOrigen!=unSectorcitoDest)
  					{
  						//help="";
  						(sprintf(help,"%d,%d ",unaPistitaOrigen,unSectorcitoOrigen));
  						strcat(letsSend,help);
  						unSectorcitoOrigen++;
  						pasoSector++;
  						if(unSectorcitoOrigen>atoi(ArrayConfAlgoritmo[5]))
  							unSectorcitoOrigen=0;
  					}
	  				(sprintf(help,"%d,%d ",unaPistitaOrigen,unSectorcitoOrigen));
	  				pasoSector++;
	  				strcat(letsSend,help);
	  				int32_t tpoVuelta = abs(60*1000/atoi(ArrayConfAlgoritmo[8]));
	  				int32_t timeCons = saltoPista*atoi(ArrayConfAlgoritmo[9]) + pasoSector*tpoVuelta;
	  				sprintf(help,"\n Tiempo Consumido: %1.1f ms \n \0 ",(saltoPista*atoi(ArrayConfAlgoritmo[9]) + pasoSector*tpoVuelta/((float)atoi(ArrayConfAlgoritmo[5]))));
	  				strcat(letsSend,help);
	  				int32_t rc = send(newSockConsole,letsSend,9*2500,0);
	  				//printf("MANDE:%d \n",rc);
					}
				free(serial);
				Atendidos++;
				//printf("\n Devolviendo sector %d \n ",SectorALeer);
				//printf("Atendidos %d \n", Atendidos);
			}
			else if(unPaquete->Tipo=='E')
			{
				if(slee14!=0)
					sleep(atoi(ArrayConfAlgoritmo[14]));
				//printf("Escribiendo sector %d \n",ColaPedidos[posicion].Sector);
				Atendidos++;
				//printf("Atendidos %d \n", Atendidos);
				EscribirSector(ColaPedidos[posicion].Sector,ColaPedidos[posicion].Datos);
			}
			ColaPedidos[posicion].Tipo='0';
			free(unPaquete->Datos);
			free(unPaquete);
		}

	}
}

char* ConvertirCHS(int32_t unSector)
{
		int32_t unaPistita=unSector / atoi(ArrayConfAlgoritmo[5]);;
		int32_t unSectorcito=unSector - unaPistita*(atoi(ArrayConfAlgoritmo[5]));
		char* letsSend=malloc(4+1+4);
		sprintf(letsSend,"%d,%d",unaPistita,unSectorcito);
		return letsSend;
}

void IniciarCSCAN()
{
	int32_t Atendidos = 0;
	int32_t i = 0;
	//printf("Algoritmo sin inanición, CSCAN \n ");
	Cabezal=0;
	int32_t posicion=-1;
	int32_t slee15 = atoi(ArrayConfAlgoritmo[15]);
	int32_t slee14 = atoi(ArrayConfAlgoritmo[14]);
	IniciarColas();
	int32_t fd = fileno_unlocked(archDisco);
	posix_fadvise(fd,0,0,2);
	/*for(i=0;i<10;i++)
	{
		Solicitud unPaquete;
		unPaquete.Datos;
		RandomGG(unPaquete.ID,16);
		unPaquete.Tipo='L';
		unPaquete.Sector=rand() % 99;
		EncolarPedido(unPaquete);
	}*/
	int32_t contarSub=0;
	while(1)
	{
		int32_t posicion=-1;
		int32_t cabezalAux=0;
		///consumir cola de pedidos ColaPedidos y desencolar segun la distancia de pistas
		int32_t SectorALeer=-1;
		int32_t buscame = -1;
		Solicitud SubListaSCAN[TAMANO_COLA];
		for(i=0;i<TAMANO_COLA;i++)
		{
			if(((ColaPedidos[i].Tipo=='L') || (ColaPedidos[i].Tipo=='E')) && (SectorALeer==-1))
			{
				SubListaSCAN[i]=ColaPedidos[i];
				contarSub++;
			}
		}

		int32_t sectores = atoi(ArrayConfAlgoritmo[5])*atoi(ArrayConfAlgoritmo[12]);
		int32_t letsCil=0;
		int32_t letsSec=0;
		int32_t posSectFix=0;
		Paquete* unPaquete;
		if(contarSub>0)
		{
		for(letsCil=0;letsCil<atoi(ArrayConfAlgoritmo[12]);letsCil++)
		{
				for(i=0;i<TAMANO_COLA;i++)
				{
					if(((SubListaSCAN[i].Tipo=='L') || (SubListaSCAN[i].Tipo=='E')))
					{
						if((SubListaSCAN[i].Sector/atoi(ArrayConfAlgoritmo[5])==letsCil))
						{
							if(ColaPedidos[i].Tipo=='L')
								{
								cabezalAux=Cabezal;
								unPaquete = ArmarPaquete(i);
								char* serial;
												serial = Serializar(unPaquete);
												int32_t posta = 0;
												for(int32_t cc = 0; cc<16;cc++)
												{
													if(unPaquete->ID[cc]!=IDTrace[cc])
														posta=1;
												}
												int sendeame;
												if(posta==1)
												{
													if(slee15!=0)
														sleep(atoi(ArrayConfAlgoritmo[15]));
													pthread_mutex_lock (&mutexBuffer);
													sendeame = send(ColaPedidos[i].Socket,serial,512+16+1+2+4,0);
													printf("Procesando sector %d \n",ColaPedidos[i].Sector);
													pthread_mutex_unlock (&mutexBuffer);
													if(sendeame<0)
														printf("Error en Send. \n");
													if(strcmp(ArrayConfAlgoritmo[3],"ON")==0)
													{
													////LOGGG
													char* Actual = malloc(9);
																										Actual=ConvertirCHS(cabezalAux);
																						  				char* letsSend = malloc(9*2500);
																						  				char* help = malloc(100);
																						  				sprintf(help,"Posicion Actual:%s \n",Actual);
																						  				strcat(letsSend,help);
																						  				Actual="\0";
																						  				Actual=ConvertirCHS(unPaquete->Sector);

																						  				sprintf(help,"Solicitado:%s \n",Actual);
																						  				strcat(letsSend,help);
																						  				int32_t saltoPista = 0;
																						  				int32_t pasoSector=0;
																						  				char* finalSend=(char*)malloc(9*2500);
																						  				int32_t unaPistitaOrigen=cabezalAux / atoi(ArrayConfAlgoritmo[5]);;
																						  				int32_t unSectorcitoOrigen=cabezalAux - unaPistitaOrigen*(atoi(ArrayConfAlgoritmo[5]));
																						  				int32_t unaPistitaDest=unPaquete->Sector / atoi(ArrayConfAlgoritmo[5]);;
																						  				int32_t unSectorcitoDest=unPaquete->Sector - unaPistitaDest*(atoi(ArrayConfAlgoritmo[5]));
																						  				strcat(letsSend,"Sectores Recorridos: ");
																						  				if(unaPistitaOrigen<unaPistitaDest)
																						  				{
																						  					//Voy subiendo de pistas
																						  					while(unaPistitaOrigen!=unaPistitaDest)
																						  					{
																						  						(sprintf(help,"%d,%d ",unaPistitaOrigen,unSectorcitoOrigen));
																						  						strcat(letsSend,help);
																						  						unaPistitaOrigen++;
																						  						saltoPista++;
																						  					}
																						  				}
																						  				else if (unaPistitaOrigen>unaPistitaDest)
																						  				{
																						  					//Bajo de pistas
																						  					while(unaPistitaOrigen!=unaPistitaDest)
																						  					{
																						  						(sprintf(help,"%d,%d ",unaPistitaOrigen,unSectorcitoOrigen));
																						  						strcat(letsSend,help);
																						  						unaPistitaOrigen--;
																						  						saltoPista++;
																						  					}
																						  				}
																						  				//Ya estoy en la pista, falta correr sobre la misma
																					  					while(unSectorcitoOrigen!=unSectorcitoDest)
																					  					{
																					  						//help="";
																					  						(sprintf(help,"%d,%d ",unaPistitaOrigen,unSectorcitoOrigen));
																					  						strcat(letsSend,help);
																					  						unSectorcitoOrigen++;
																					  						pasoSector++;
																					  						if(unSectorcitoOrigen>atoi(ArrayConfAlgoritmo[5]))
																					  							unSectorcitoOrigen=0;
																					  					}
																						  				pthread_mutex_lock(&mutexCabezal);
																						  				Cabezal=unaPistitaOrigen*atoi(ArrayConfAlgoritmo[5])+unSectorcitoOrigen+1;
																						  				cabezalAux=Cabezal;
																						  				pthread_mutex_unlock(&mutexCabezal);
																						  				pasoSector++;
																						  				(sprintf(help,"%d,%d ",unaPistitaOrigen,unSectorcitoOrigen));
																						  				strcat(letsSend,help);
																						  				int32_t tpoVuelta = abs(60*1000/atoi(ArrayConfAlgoritmo[8]));
																						  				int32_t timeCons = (saltoPista*atoi(ArrayConfAlgoritmo[9]) + pasoSector*tpoVuelta);
																						  				sprintf(help,"\n Tiempo Consumido: %1.1f ms \n \0 ",(saltoPista*atoi(ArrayConfAlgoritmo[9]) + pasoSector*tpoVuelta/((float)atoi(ArrayConfAlgoritmo[5]))));
																						  				strcat(letsSend,help);
																						  				escribir_logfile("DiscoSO", 0, INFOs, letsSend);
																						  				//printf("MANDE:%d \n",rc);
													////LOGGG
													}
												}
												else
													{
													char* Actual = malloc(9);
													Actual=ConvertirCHS(cabezalAux);
									  				char* letsSend = malloc(9*2500);
									  				char* help = malloc(100);
									  				sprintf(help,"Posicion Actual:%s \n",Actual);
									  				strcat(letsSend,help);
									  				Actual="\0";
									  				Actual=ConvertirCHS(unPaquete->Sector);

									  				sprintf(help,"Solicitado:%s \n",Actual);
									  				strcat(letsSend,help);
									  				int32_t saltoPista = 0;
									  				int32_t pasoSector=0;
									  				char* finalSend=(char*)malloc(9*2500);
									  				int32_t unaPistitaOrigen=cabezalAux / atoi(ArrayConfAlgoritmo[5]);;
									  				int32_t unSectorcitoOrigen=cabezalAux - unaPistitaOrigen*(atoi(ArrayConfAlgoritmo[5]));
									  				int32_t unaPistitaDest=unPaquete->Sector / atoi(ArrayConfAlgoritmo[5]);;
									  				int32_t unSectorcitoDest=unPaquete->Sector - unaPistitaDest*(atoi(ArrayConfAlgoritmo[5]));
									  				strcat(letsSend,"Sectores Recorridos: ");
									  				if(unaPistitaOrigen<unaPistitaDest)
									  				{
									  					//Voy subiendo de pistas
									  					while(unaPistitaOrigen!=unaPistitaDest)
									  					{
									  						(sprintf(help,"%d,%d ",unaPistitaOrigen,unSectorcitoOrigen));
									  						strcat(letsSend,help);
									  						unaPistitaOrigen++;
									  						saltoPista++;
									  					}
									  				}
									  				else if (unaPistitaOrigen>unaPistitaDest)
									  				{
									  					//Bajo de pistas
									  					while(unaPistitaOrigen!=unaPistitaDest)
									  					{
									  						(sprintf(help,"%d,%d ",unaPistitaOrigen,unSectorcitoOrigen));
									  						strcat(letsSend,help);
									  						unaPistitaOrigen--;
									  						saltoPista++;
									  					}
									  				}
									  				//Ya estoy en la pista, falta correr sobre la misma
								  					while(unSectorcitoOrigen!=unSectorcitoDest)
								  					{
								  						//help="";
								  						(sprintf(help,"%d,%d ",unaPistitaOrigen,unSectorcitoOrigen));
								  						strcat(letsSend,help);
								  						unSectorcitoOrigen++;
								  						pasoSector++;
								  						if(unSectorcitoOrigen>atoi(ArrayConfAlgoritmo[5]))
								  							unSectorcitoOrigen=0;
								  					}
									  				pthread_mutex_lock(&mutexCabezal);
									  				Cabezal=unaPistitaOrigen*atoi(ArrayConfAlgoritmo[5])+unSectorcitoOrigen+1;
									  				cabezalAux=Cabezal;
									  				pthread_mutex_unlock(&mutexCabezal);
									  				pasoSector++;
									  				(sprintf(help,"%d,%d ",unaPistitaOrigen,unSectorcitoOrigen));
									  				strcat(letsSend,help);
									  				int32_t tpoVuelta = abs(60*1000/atoi(ArrayConfAlgoritmo[8]));
									  				int32_t timeCons = (saltoPista*atoi(ArrayConfAlgoritmo[9]) + pasoSector*tpoVuelta);
									  				sprintf(help,"\n Tiempo Consumido: %1.1f ms \n \0 ",(saltoPista*atoi(ArrayConfAlgoritmo[9]) + pasoSector*tpoVuelta/((float)atoi(ArrayConfAlgoritmo[5]))));
									  				strcat(letsSend,help);
									  				int32_t rc = send(newSockConsole,letsSend,9*2500,0);
									  				//printf("MANDE:%d \n",rc);
													}
												free(serial);
												Atendidos++;
												free(unPaquete->Datos);
												free(unPaquete);
								}
							else if(ColaPedidos[i].Tipo=='E')
								{
								if(slee14!=0)
									sleep(atoi(ArrayConfAlgoritmo[14]));
								//printf("Escribiendo sector %d \n",ColaPedidos[i].Sector);
								EscribirSector(ColaPedidos[i].Sector,ColaPedidos[i].Datos);
								}
								ColaPedidos[i].Tipo='0';
						}
					}
			}
		}
		for(i=0;i<TAMANO_COLA;i++)
			SubListaSCAN[i].Tipo='0';
		}
	}
}
